﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Automation;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WinRpaLib;
using static System.Net.Mime.MediaTypeNames;


public class UiElementQuery
{
    private static readonly char GT = '>';
    private static readonly char LB = '[';
    private static readonly char RB = ']';
    private static readonly char GT_S = '\u204B';
    private static readonly char LB_S = '\u206B';
    private static readonly char RB_S = '\u207B';

    private static readonly char[,] _levelSplitChar = new char[,]
    {
        { GT, GT_S },
        { LB, LB_S },
        { RB, RB_S }
    };


    static private string ReplaceOutsideQuotes(string input)
    {
        StringBuilder sb = new StringBuilder();
        bool inQuotes = false;

        foreach (char c in input)
        {
            if (c == '"')
            {
                inQuotes = !inQuotes; // Toggle the inQuotes state
                sb.Append(c);
            }
            else if (!inQuotes)
            {
                char c2 = c;
                for (int i = 0; i < _levelSplitChar.GetLength(0); i++)
                { 
                    if(_levelSplitChar[i,0] == c)
                    {
                        c2 = _levelSplitChar[i, 1];
                    }
                }
                sb.Append(c2);
            }
            else
            {
                sb.Append(c);
            }
        }

        return sb.ToString();
    }

    public static UiElementQuery ParserFromPath(string selector)
    {
        selector = selector.Trim().Trim(GT);
        selector = ReplaceOutsideQuotes(selector);

        string[] selector_list = selector.Split(GT_S);

        UiElementQuery root = new UiElementQuery();
        UiElementQuery parent = root;
        foreach (string s1 in selector_list)
        {
            string s2 = s1.Trim();

            // 匹配主要元素
            
            string mainElement = s2.Substring(0, (s2.IndexOf(LB_S) == -1 ? s2.Length: s2.IndexOf(LB_S)));
            mainElement = mainElement.Trim();

            string pattern1 = string.Format(@"\{0}([^\{0}\{1}]*)\{1}", LB_S, RB_S);

            // 注意：这个正则表达式假设双引号内的内容不会被转义（即没有 \" 这样的情况）。
            // 如果你的字符串中可能包含转义的双引号，你需要一个更复杂的正则表达式来处理它。

            MatchCollection matches = Regex.Matches(s2, pattern1);

            Dictionary<string, AttributesType> attributes = new Dictionary<string, AttributesType>();
            foreach (Match match1 in matches)
            {
                Console.WriteLine(match1.Value);
                String input = match1.Value.Trim();
                string pattern2 = string.Format(@"\{0}([^\{0}\{1}=]+)([*@!=]?=)([^\{0}\{1}]*)\{1}", LB_S, RB_S);

                Match match = Regex.Match(input, pattern2);
                if (match.Success)
                {
                    string key = match.Groups[1].Value.Replace("\\\"", "\""); // 处理可能的转义双引号（如果有的话）
                    string separator = match.Groups[2].Value;
                    string value = match.Groups[3].Value.Trim('\"').Replace("\\\"", "\""); // 处理可能的转义双引号（如果有的话）
                    // 注意：这里的 Replace("\\\"", "\"") 是为了处理字符串中可能存在的转义双引号。
                    // 在你的示例中并没有这样的转义字符，但如果存在，这个替换是必要的。
                    // 如果你的字符串中确实不包含转义的双引号，你可以去掉这个替换操作。

                    Console.WriteLine($"Key: {key}, Separator: {separator}, Value: {value}");

                    attributes[key] = new AttributesType(key, separator, value);

                }
                else
                {
                    Console.WriteLine($"Failed to parse input: {match1.Value}");
                }
            }


            parent.Child = new UiElementQuery(mainElement, attributes);
            parent = parent.Child;
        }

        return root.Child;
    }

    public UiElementQuery()
    { }

    public UiElementQuery(string ElementType, Dictionary<string, AttributesType> Attributes)
    {
        this.ElementType = ElementType.Trim();
        this.Attributes = Attributes ?? new Dictionary<string, AttributesType>();
    }
    public string ElementType { get; set; }
    public Dictionary<string, AttributesType> Attributes { get; set; }

    public UiElementQuery Child { get; set; }

    public class AttributesType
   {
        public AttributesType(string key, string @operator, string value)
        {
            Key = key;
            Operator = @operator;
            Value = value;
        }

        public String Key { get; set; }
        public String Operator { get; set; }
        public String Value { get; set; }

    }
}

public class UiElementFinder
{

    public static AutomationElement FindElementBySelecter(string selecter, AutomationElement rootElement = null)
    {
        if (rootElement == null)
        {
            // If no root element is provided, start from the desktop
            rootElement = AutomationElement.RootElement;
        }

        var query = UiElementQuery.ParserFromPath(selecter);
        return FindElement(rootElement, query);
    }

    public static AutomationElement FindElement(AutomationElement rootElement, UiElementQuery query)
    {
        Console.WriteLine($"Name: {rootElement.Current.Name}, ControlType: {rootElement.Current.ControlType}");

        // Find elements matching the current query level
        Condition condition = BuildCondition(query);

        var elements = rootElement.FindAll(TreeScope.Descendants, condition);

        if (elements.Count == 0)
        {
            return null; // No matching elements found at this level
        }

        if (query.Child == null)
        {
            // If there's no child query, return the first matching element
            return elements[0];
        }
        else
        {
            // Recursively search for the child element
            foreach (AutomationElement element in elements)
            {
                var childElement = FindElement(element, query.Child);
                if (childElement != null)
                {
                    return childElement; // Return the first found child element that matches the child query
                }
            }

            return null; // No matching child elements found
        }
    }

    private static Condition BuildCondition(UiElementQuery query)
    {
        List<Condition> conditions = new List<Condition>();
        conditions.Add(PropertyCondition.TrueCondition);
        conditions.Add(PropertyCondition.TrueCondition);
        if (!String.IsNullOrEmpty(query.ElementType))
        {
            conditions.Add(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlTypeHelper.GetControlTypeFromName(query.ElementType)));
        }
        if (query.Attributes.ContainsKey("Name"))
        {
            conditions.Add(new PropertyCondition(AutomationElement.NameProperty, query.Attributes["Name"].Value));
        }
        if (query.Attributes.ContainsKey("Class"))
        {
            conditions.Add(new PropertyCondition(AutomationElement.ClassNameProperty, query.Attributes["Class"].Value));
        }

        ////扩展实现  可以通过重写PropertyCondition，来实现 [!=] [*=]等其他查询演算子功能。


        return new AndCondition(conditions.ToArray());
    }

}
